﻿using OnWork.DataCenter.Utils.Caches;
using OnWork.DataCenter.Utils.Formula;
using System.Collections.Concurrent;
using System.Collections.Generic;

namespace OnWork.DataCenter.Utils
{
    /// <summary>
    /// 公式帮助类
    /// </summary>
    public static class FormulaHelp
    {
        /// <summary>
        /// 字符串是否包含公式 公式格式${ }
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private static bool StrngHasFormula(string input)
        {
            if (!string.IsNullOrEmpty(input))
            {
                return input.Contains("${"); //包含则直接返回
            }
            return false;
        }

        /// <summary>
        /// 公式处理
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string Formula(this string input, object? self = null, IDictionary<string, object>? parameters = null)
        {
            //如果有公式
            if (StrngHasFormula(input))
            {
                return ReplaceFormula(input, VariablesCache.GETDict(), self, parameters);
            }
            return input;
        }

        /// <summary>
        /// 替换代码里的公式
        /// </summary>
        /// <param name="input"></param>
        /// <param name="envParams"></param>
        /// <returns></returns>
        private static string ReplaceFormula(string input, ConcurrentDictionary<string, string> envParams, object? self, IDictionary<string, object>? parameters)
        {
            //获取字符串去重
            var para = MidStrEx(input, "${", "}").Distinct();
            if (para != null && para.Count() > 0)
            {
                foreach (var item in para)
                {
                    var old = "${" + item + "}";
                    //1.首先判断公共环境变量的值
                    if (envParams != null)
                    {
                        bool isContain = envParams.ContainsKey(item);
                        if (isContain)
                        {
                            input = input.Replace(old, envParams[item]);
                            continue;
                        }
                    }
                    //3. 如果还没有解析完 则使用公式进行解析
                    string valF = FormulaConver(item, self, parameters).ToString();
                    input = input.Replace(old, valF);
                }
            }
            return input;
        }

        /// <summary>
        /// 公式解析
        /// </summary>
        /// <param name="express">传入的公式</param>
        /// <returns></returns>
        public static object FormulaConver(string express, object? self, IDictionary<string, object>? parameters)
        {
            //使用Lamber方法
            var expr = new NCalc.Expression(express);
            Func<ExpressionContext, object> f = expr.ToLambda<ExpressionContext, object>();
            var context = new ExpressionContext();
            context.Self = self;
            context.Parameters = parameters;
            return f(context);


            ////使用老方法
            //if (parameters != null && parameters.Count > 0)
            //{
            //    var expr = new NCalc.Expression(express);
            //    foreach (var item in parameters)
            //    {
            //        expr.Parameters.Add(item.Key, item.Value); //增加参数
            //    }
            //    return expr.Evaluate();
            //}
            //else
            //{
            //    //使用Lamber方法
            //    var expr = new NCalc.Expression(express);
            //    Func<ExpressionContext, object> f = expr.ToLambda<ExpressionContext, object>();
            //    var context = new ExpressionContext();
            //    context.Self = self;
            //    context.Parameters = parameters;
            //    return f(context);
            //}
        }


        /// <summary>
        /// 获取开始和结束字符串的值
        /// </summary>
        /// <param name="sourse"></param>
        /// <param name="startstr"></param>
        /// <param name="endstr"></param>
        /// <returns></returns>
        private static List<string> MidStrEx(string sourse, string startstr, string endstr)
        {
            //返回的列表
            List<string> results = new List<string>();

            string result;
            int startindex, endindex, index = 0;

            while (true)
            {
                startindex = sourse.IndexOf(startstr, index); //获取开始字符串位置
                if (startindex == -1) //未找到
                    return results;
                endindex = sourse.IndexOf(endstr, startindex); //获取结束字符位置
                if (endindex == -1)
                    return results;
                result = sourse.Substring(startindex + startstr.Length, endindex - (startindex + startstr.Length));
                results.Add(result);
                index = endindex;
            }
        }
    }
}